package com.qidian.common.beans;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import com.qidian.common.ClientStatus;
import com.qidian.common.Constants;
import com.qidian.common.TableMeta;
import com.qidian.util.StringUtil;


/**
 * 客户端信息
 * 
 * */
public class ClientBean implements ISyncBean
{
	//客户端ID
	Long clientId = -1L;
	//客户端用户名
	String clientName = null;
	//客户端密码
	String password = null ;
	
	//已答题数
	volatile int answered = 0;
	AtomicInteger answeredIncr = new AtomicInteger(0) ;
	
	//答错的题数
	volatile int wrong = 0;
	AtomicInteger wrongIncr = new AtomicInteger(0) ;
	
	//所有答对的题的累积点数
	volatile double point = 0.0;
	AtomicLong pointIncr1000 = new AtomicLong(0L) ;
	
	String name = null ;
	String phone = null ;
	int localSize = 5 ;// 本地队列
	int msgType = -1 ;// 允许接收的消息类型
	
	// 至昨天为止，累积计数信息
	int answeredYesterday = 0 ;
	int wrongYesterday = 0 ;
	double pointYesterday = 0.0f ;

	
	//客户端状态
	int status = ClientStatus.NoActive.getStatusCode();
	
	volatile long lastActiveTime = 0;
	
	String zhifubao = null ;
	int workTimeStart = 0 ;
	int workTimeEnd = 24 ;
	
    public static final String clearSql = "delete from " + TableMeta.table_client +
				" where " + TableMeta.column_status + " = -1 ";

	
	public void setDeleted()
	{
		this.status = ClientStatus.DELETED.getStatusCode() ;
	}
	public boolean isDeleted()
	{
		return this.status == ClientStatus.DELETED.getStatusCode() ;
	}
	
	public Long getClientId() {
		return clientId;
	}
	public void setClientId(Long clientId) {
		this.clientId = clientId;
	}
	public String getClientName() {
		return clientName;
	}
	public void setClientName(String clientName) {
		this.clientName = clientName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public Integer getAnswered() {
		return answered;
	}
	public void setAnswered(Integer answered) {
		this.answered = answered;
	}
	public Integer getWrong() {
		return wrong;
	}
	public void setWrong(Integer wrong) {
		this.wrong = wrong;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(ClientStatus status) {
		this.status = status.getStatusCode();
	}
	public boolean isActive()
	{
		return status == ClientStatus.Active.getStatusCode() ;
	}
	public static ClientBean toClientBean(ResultSet rs) throws SQLException 
	{
		ClientBean clientBean = new ClientBean() ;
		clientBean.setClientId(rs.getLong(TableMeta.column_client_id)) ;
		clientBean.setClientName(rs.getString(TableMeta.column_client_user_name)) ;
		clientBean.setPassword(rs.getString(TableMeta.column_client_password)) ;
		clientBean.setAnswered(rs.getInt(TableMeta.column_answer_count)) ;
		clientBean.setWrong(rs.getInt(TableMeta.column_wrong_count)) ;
//		clientBean.setPoint(rs.getInt(TableMeta.column_point)) ;
		clientBean.setPoint(rs.getDouble(TableMeta.column_point)) ;
		clientBean.setStatus(rs.getInt(TableMeta.column_status)) ;
		clientBean.setName(rs.getString(TableMeta.column_name)) ;
		clientBean.setPhone(rs.getString(TableMeta.column_phone)) ;
//		clientBean.setZhifubao(rs.getString(TableMeta.column_zhifubao)) ;
//		clientBean.setWorkTimeStart(rs.getInt(TableMeta.column_work_time_start)) ;
//		clientBean.setWorkTimeEnd(rs.getInt(TableMeta.column_work_time_end)) ;
		
//		clientBean.setAnsweredYesterday(clientBean.answered) ;
//		clientBean.setWrongYesterday(clientBean.wrong) ;
//		clientBean.setPointYesterday(clientBean.point) ;
		return clientBean;
	}
	
	public String getStasticSql(java.util.Date date)
	{
		return null ;
	}
	
	
	/**
	 * 标记消息被该客户端处理
	 * 
	 * */
	public void markMsg(MessageBean msg)
	{
		msg.setClientId(clientId) ;
		msg.setProcessing() ;
		msg.setRequestTime(System.currentTimeMillis()) ;
	}
	
    @Override
    public PreparedStatement getPreparedStatement(Connection conn)
            throws SQLException
    {
        final String sql = "update " + TableMeta.table_client + " set " + 
                        TableMeta.column_answer_count + " = " + TableMeta.column_answer_count + " + ? , "+
                        TableMeta.column_wrong_count + " = " + TableMeta.column_wrong_count + " + ? ," +
                        TableMeta.column_point + " = " + TableMeta.column_point + " + ? ," +
                        TableMeta.column_status + " = ? " +
                        " where " + TableMeta.column_client_id + " = ? ";
        return conn.prepareStatement(sql) ;
    }
    
    @Override
    public boolean needSynchronized()
    {
        return true;
    }
    
    @Override
    public boolean setParameters(PreparedStatement ps) 
    {

        try
        {
            ps.setInt(1, answeredIncr.getAndSet(0)) ;
            ps.setInt(2, wrongIncr.getAndSet(0)) ;
            ps.setDouble(3, pointIncr1000.getAndSet(0)/1000.00) ;
            ps.setInt(4, status) ;
            ps.setLong(5, clientId) ;
        }
        catch (SQLException e)
        {
            e.printStackTrace();
            return false ;
        }
        
        return true;
    }
    
    /**
     * 增加答题数量、点数
     * 
     * */
    public synchronized void addAnswerCount(int increment,double point)
    {
        this.answered += increment ;
        this.answeredIncr.addAndGet(increment) ;
        this.point += Constants.point_ratio_current*point ;
        this.pointIncr1000.addAndGet((new Double(Constants.point_ratio_current*1000*point).longValue())) ;
    }
    
    public long getLastActiveTime()
    {
        return lastActiveTime;
    }
    public void setLastActiveTime(long lastActiveTime)
    {
        this.lastActiveTime = lastActiveTime;
    }
    public void setNoActive()
    {
        this.status = ClientStatus.NoActive.getStatusCode() ;
        this.lastActiveTime = 0 ;
    }
    /**
     * 60秒内无动作，客户端判定为僵死
     * 
     * */
    public boolean isZombie()
    {
        return System.currentTimeMillis() - lastActiveTime >= Constants.ZombieInterval*1000 ;
    }
    
    /**
     * 增加错题数量，同时减少点数
     * 
     * @param num_wrong_answers 错题数增量
     * @param point 错题点数
     * 
     * */
    public synchronized void addWrongCount(int num_wrong_answers, double point)
    {
        this.wrong += num_wrong_answers ;
        this.wrongIncr.addAndGet(num_wrong_answers) ;
        this.point -= Constants.point_ratio_current*point ;
        this.pointIncr1000.addAndGet(-(new Double(Constants.point_ratio_current*1000*point).longValue())) ;
        
    }
	public double getPoint() {
		return point;
	}
	public void setPoint(double points) {
		this.point = points;
	}
	
	public static void main(String[] args)
	{
        final String sql = "update " + TableMeta.table_client + " set " + 
        TableMeta.column_answer_count + " = ? , "+
        TableMeta.column_wrong_count + " = ? ," +
        TableMeta.column_point + " = ? " +
        " where " + TableMeta.column_client_id + " = ? ";
        System.out.println(sql) ;
        
        java.util.Date date = new java.util.Date() ;
        ClientBean cb = new ClientBean() ;
        System.out.println(cb.getStasticInsertSql(date)) ;
        System.out.println(cb.getStasticUpdateSql(date)) ;
        System.out.println(cb.getStasticSql(date)) ;
	}
	public void setStatus(int status) {
		this.status = status;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public int getLocalSize() {
		return localSize;
	}
	public void setLocalSize(int localSize) {
		this.localSize = localSize;
	}
	public int getMsgType() {
		return msgType;
	}
	public void setMsgType(int msgType) {
		this.msgType = msgType;
	}
	public int getAnsweredToday() {
		return answered-answeredYesterday;
	}
	public void setAnsweredYesterday(int answeredYesterday) {
		this.answeredYesterday = answeredYesterday;
	}
	public int getWrongToday() {
		return wrong-wrongYesterday;
	}
	public void setWrongYesterday(int wrongToday) {
		this.wrongYesterday = wrongToday;
	}
	public double getPointToday() {
		return point - pointYesterday;
	}
	public void setPointYesterday(double pointToday) {
		this.pointYesterday = pointToday;
	}
	
	/**
	 * 重置所有计数信息
	 * 
	 * */
	public void reset(){
		this.answeredIncr.addAndGet(-this.answered) ;
		this.answered = 0 ;
		
		this.wrongIncr.addAndGet(-this.wrong) ;
		this.wrong = 0 ;
		
		this.pointIncr1000.addAndGet(-(long)(this.point*1000.0)) ;
		this.point = 0.0 ;
		
		this.answeredYesterday = 0 ;
		this.wrongYesterday = 0 ;
		this.pointYesterday = 0.0 ;
	}
	
	/**
	 * 记录昨天的计数信息
	 * 
	 * */
	public void resetStastic() {
		this.answeredYesterday = this.answered ;
		this.wrongYesterday = this.wrong ;
		this.pointYesterday = this.point ;
	}
	
	/**
	 * 插入新的统计记录，防止重复插入
	 * 
	 * */
	public String getStasticInsertSql(java.util.Date date)
	{
		String sql = "insert into " + TableMeta.table_stastic_client + " values('" +
						StringUtil.toDateString(date) + "'," + this.clientId+",0,0,0.0," +
								+this.answeredYesterday+","+this.wrongYesterday+","+this.pointYesterday+")" ;
//		"0,0,0.0);";
		sql = " INSERT INTO " + TableMeta.table_stastic_client+" (" +
		TableMeta.column_day+","+
		TableMeta.column_client_id+","+
		TableMeta.column_answer_count+","+
		TableMeta.column_wrong_count+","+
		TableMeta.column_point+","+
		TableMeta.column_answer_count_yesterday+","+
		TableMeta.column_wrong_count_yesterday+","+
		TableMeta.column_point_yesterday+") SELECT '"+
		StringUtil.toDateString(date) + "'," + this.clientId+",0,0,0.0," +
		+this.answeredYesterday+","+this.wrongYesterday+","+this.pointYesterday+
		" FROM dual WHERE not exists ( SELECT * from " + TableMeta.table_stastic_client+
		" WHERE " +TableMeta.column_client_id+ " = "+ this.clientId + " and " +
				TableMeta.column_day +" = '"+StringUtil.toDateString(date)+"')";
		return sql ;
	}
	
	/**
	 * 更新每日统计信息
	 * 
	 * */
	public String getStasticUpdateSql(java.util.Date date)
	{
		int deltaAnswered = getAnsweredToday() ;
		int deltaWrong = getWrongToday() ;
		double deltaPoint = getPointToday() ;
		
		String sql = " update " + TableMeta.table_stastic_client + " set "
						+TableMeta.column_answer_count+"="+ deltaAnswered+","
						+TableMeta.column_wrong_count+"="+ deltaWrong+","
						+TableMeta.column_point+"="+ deltaPoint+","
						+TableMeta.column_answer_count_yesterday+"="+ this.answeredYesterday+","
						+TableMeta.column_wrong_count_yesterday+"="+ this.wrongYesterday+","
						+TableMeta.column_point_yesterday+"="+ this.pointYesterday
						+" where " + TableMeta.column_day+" = '" + StringUtil.toDateString(date) + "' and "
						+ TableMeta.column_client_id + " = " + this.clientId;
		return sql ;
	}
	
	/**
	 * 获取正确率
	 * 
	 * */
	public double getAcurateRatio()
	{
		if (this.answered <= 0)
			return 1.00 ;
		return (1.00 - wrong*1.0/answered)*10000/10000.0; 
	}
	public String getZhifubao() {
		return zhifubao;
	}
	public void setZhifubao(String zhifubao) {
		this.zhifubao = zhifubao;
	}
	public int getWorkTimeStart() {
		return workTimeStart;
	}
	public void setWorkTimeStart(int workTimeStart) {
		this.workTimeStart = workTimeStart;
	}
	public int getWorkTimeEnd() {
		return workTimeEnd;
	}
	public void setWorkTimeEnd(int workTimeEnd) {
		this.workTimeEnd = workTimeEnd;
	}
	
}
